package top.tangyh.lamp.care.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.util.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.tangyh.basic.exception.BizException;
import top.tangyh.lamp.care.common.ChangeExeYaoStatusEnum;
import top.tangyh.lamp.care.common.ExeYaoSortFieldEnum;
import top.tangyh.lamp.care.common.ExeYaoStatusNewEnum;
import top.tangyh.lamp.care.entity.BHl7Event;
import top.tangyh.lamp.care.entity.BHl7YzYaoPlan;
import top.tangyh.lamp.care.mapper.BHl7EventMapper;
import top.tangyh.lamp.care.mapper.BHl7YzYaoExeMapper;
import top.tangyh.lamp.care.mapper.BHl7YzYaoPlanMapper;
import top.tangyh.lamp.care.service.BHl7YzYaoExeService;
import top.tangyh.basic.base.service.impl.SuperServiceImpl;
import top.tangyh.lamp.care.manager.BHl7YzYaoExeManager;
import top.tangyh.lamp.care.entity.BHl7YzYaoExe;
import top.tangyh.lamp.care.vo.query.ExeYaoQueryVO;
import top.tangyh.lamp.care.vo.result.ExeYaoOutVO;
import top.tangyh.lamp.care.vo.result.ExeYaoShortOutVO;
import top.tangyh.lamp.care.vo.result.RkYongYaoOutVO;
import top.tangyh.lamp.care.vo.save.RkYongYaoInVO;
import top.tangyh.lamp.common.constant.EventEnum;
import top.tangyh.lamp.common.utils.PDateUtils;
import top.tangyh.lamp.common.utils.YDateUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static top.tangyh.lamp.common.constant.CommonConstant.NO_NUMBER;
import static top.tangyh.lamp.common.constant.CommonConstant.YES_NUMBER;

/**
 * <p>
 * 业务实现类
 * 医嘱实际执行表
 * </p>
 *
 * @author zqb
 * @date 2024-07-22 15:09:14
 * @create [2024-07-22 15:09:14] [zqb] [代码生成器生成]
 */
@Slf4j
@RequiredArgsConstructor
@Service
@Transactional(readOnly = true)
public class BHl7YzYaoExeServiceImpl extends SuperServiceImpl<BHl7YzYaoExeManager, Integer, BHl7YzYaoExe> implements BHl7YzYaoExeService {

    private final BHl7EventMapper eventMapper;

    private final BHl7YzYaoExeMapper bHl7YzYaoExeMapper;

    private final BHl7YzYaoPlanMapper bHl7YzYaoPlanMapper;

    public static final String MED_DELIMITER = " + ";


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRkYongYaoInfo(RkYongYaoInVO yongYaoInVO) {
        //查找入科消息 得到入科时间
        BHl7Event BHl7Event = eventMapper.selectOneByEventTypeHospitalNumber(EventEnum.RK.getEventType(), yongYaoInVO.getHospitalNumber());
        if (BHl7Event == null) {
            throw new BizException("入科时间为空,请先补齐入科时间信息");
        }
        LocalDateTime rkTime = BHl7Event.getEventTime();
        if (rkTime != null) {
            Long exeTime = yongYaoInVO.getExeTime();
            LocalDateTime exeDate = PDateUtils.getDateTimeOfTimestamp(exeTime);
            if (exeDate.isAfter(rkTime)) {
                throw new BizException("入科前用药不能晚于入科时间");
            }
        }
        BHl7YzYaoExe yaoExePO = new BHl7YzYaoExe();
        yaoExePO.setPatientIdent(yongYaoInVO.getPatientIdent());
        yaoExePO.setHospitalNumber(yongYaoInVO.getHospitalNumber());
        yaoExePO.setExeName(yongYaoInVO.getYaoName());
        yaoExePO.setMd(yongYaoInVO.getMd());
        yaoExePO.setStartTime(PDateUtils.getDateTimeOfTimestamp(yongYaoInVO.getExeTime()));
        yaoExePO.setIsDiy(YES_NUMBER);
        bHl7YzYaoExeMapper.insert(yaoExePO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRkYongYaoInfo(RkYongYaoInVO yongYaoInVO) {
        BHl7YzYaoExe yaoExePO = bHl7YzYaoExeMapper.selectById(yongYaoInVO.getId());
        if (yaoExePO != null) {
            BHl7YzYaoExe updateYaoExePO = new BHl7YzYaoExe();
            updateYaoExePO.setId(yongYaoInVO.getId());
            updateYaoExePO.setExeName(yongYaoInVO.getYaoName());
            updateYaoExePO.setMd(yongYaoInVO.getMd());
            updateYaoExePO.setStartTime(PDateUtils.getDateTimeOfTimestamp(yongYaoInVO.getExeTime()));
            bHl7YzYaoExeMapper.updateById(updateYaoExePO);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRkYongYaoInfo(Long id) {
        BHl7YzYaoExe yaoExePO = bHl7YzYaoExeMapper.selectById(id);
        if (yaoExePO != null) {
            BHl7YzYaoExe delYaoExe = new BHl7YzYaoExe();
            delYaoExe.setId(id);
            delYaoExe.setIsDeleted(YES_NUMBER);
            bHl7YzYaoExeMapper.updateById(delYaoExe);
        }
    }

    @Override
    public List<RkYongYaoOutVO> listRkYongYaoOutVO(String hospitalNumber, Long rkTimeLong) {
        LocalDateTime rkDate = PDateUtils.getDateTimeOfTimestamp(rkTimeLong);
        List<BHl7YzYaoExe> yaoExePOSList = bHl7YzYaoExeMapper.selectListByTimeHospitalNumber(hospitalNumber);
//        List<BHl7YzYaoExe> yzYaoExePOListNew = yaoExePOSList.stream().filter(e -> e.getStartTime().isBefore(rkDate)).collect(Collectors.toList());
        List<BHl7YzYaoExe> yzYaoExePOListNew = yaoExePOSList != null
                ? yaoExePOSList.stream().filter(e -> e.getStartTime() != null && e.getStartTime().isBefore(rkDate)).collect(Collectors.toList())
                : Collections.emptyList();

        List<RkYongYaoOutVO> rkYongYaoOutVOList = yzYaoExePOListNew.stream().map(RkYongYaoOutVO::new).collect(Collectors.toList());
        return rkYongYaoOutVOList;
    }

    @Override
    public List<ExeYaoOutVO> selectExeYaoListNoEventByQuery(ExeYaoQueryVO queryVO) {
        //需求变动 ： 根据分组id和时间分为一组用药，查询时间范围 为一天，后续需求文档会进行补充
        Long currentDate = queryVO.getCurrentDate();
        String hospitalNumber = queryVO.getHospitalNumber();
        if (currentDate == null || StrUtil.isBlank(hospitalNumber)) {
            throw new BizException("请输入当天时间戳和病人住院号参数");
        }
        Long workStartTime = queryVO.getWorkStartTime();
        Long workEndTime = queryVO.getWorkEndTime();
        if (workStartTime == null || workEndTime == null) {
            throw new BizException("请输入排班开始和结束时间戳");
        }
        String sortName = queryVO.getSortName();
        if (StrUtil.isBlank(sortName)) {
            throw new BizException("请输入排序字段");
        }
        //排班开始和结束时间
        String startDateStr = DateUtil.formatDateTime(DateUtil.date(workStartTime));
        String endDateStr = DateUtil.formatDateTime(DateUtil.date(workEndTime));

        List<BHl7YzYaoPlan>yaoPlanListByGroup =
                selectYaoList(null,startDateStr,endDateStr,hospitalNumber,0,queryVO.getMedicationName(), queryVO.getRouteIdent(), queryVO.getConditionIdent(),null);

        if(CollectionUtil.isEmpty(yaoPlanListByGroup)){
            return new ArrayList<>();
        }

        Map<String, List<BHl7YzYaoPlan>> groupMap = yaoPlanListByGroup.stream().collect(Collectors.groupingBy(v ->
                v.getGroupId() + "-" + PDateUtils.getLocalDateTimeToString(v.getPlanTime())   ));

        //组合成vo结果集
        List<ExeYaoOutVO> resultList = new ArrayList<>();
        //遍历是为了处理vo的属性值
        groupMap.forEach((groupIdPlanTime, yaoPlanPoList) -> {
            ExeYaoOutVO exeYaoOutVO = new ExeYaoOutVO();

            //主药在前
            List<String> medications = yaoPlanPoList.stream().sorted(Comparator.comparing(BHl7YzYaoPlan::getIsMaster).reversed()).map(BHl7YzYaoPlan::getMedication).collect(Collectors.toList());
            //药名由在同一组下的药名拼接组成
            String medicationName = String.join(MED_DELIMITER, medications);
            exeYaoOutVO.setMedicationName(medicationName);
            yaoPlanPoList.forEach(yxHl7YzYaoPlanPO -> {
                //根据主药组合vo
                if (yxHl7YzYaoPlanPO.getIsMaster().equals(YES_NUMBER)) {
                    BeanUtil.copyProperties(yxHl7YzYaoPlanPO, exeYaoOutVO);
                    exeYaoOutVO.setYaoExeTime(yxHl7YzYaoPlanPO.getExeTime());
                    exeYaoOutVO.setYaoStatus(yxHl7YzYaoPlanPO.getExeStatus());
                    exeYaoOutVO.setMasterId(yxHl7YzYaoPlanPO.getId());

                    exeYaoOutVO.setInputType(yxHl7YzYaoPlanPO.getInputType());
                    exeYaoOutVO.setRemarks(yxHl7YzYaoPlanPO.getRemarks());
                    exeYaoOutVO.setSignature1(yxHl7YzYaoPlanPO.getSignature1());
                    exeYaoOutVO.setSignature2(yxHl7YzYaoPlanPO.getSignature2());
                    exeYaoOutVO.setIsDiy(yxHl7YzYaoPlanPO.getIsDiy());
                    exeYaoOutVO.setDyAmount(yxHl7YzYaoPlanPO.getDyAmount());
                    exeYaoOutVO.setDyAmountUnit(yxHl7YzYaoPlanPO.getDyAmountUnit());
                    exeYaoOutVO.setCreatedTime(yxHl7YzYaoPlanPO.getCreatedTime());
                    exeYaoOutVO.setUpdatedBy(yxHl7YzYaoPlanPO.getUpdatedBy());
                    exeYaoOutVO.setCreatedBy(yxHl7YzYaoPlanPO.getCreatedBy());
                    if(null != yxHl7YzYaoPlanPO.getExeStatus() && (yxHl7YzYaoPlanPO.getExeStatus().equals("1") || yxHl7YzYaoPlanPO.equals("4"))){
                        exeYaoOutVO.setEndTimestamp(yxHl7YzYaoPlanPO.getExeTime());
                        exeYaoOutVO.setStartTimestamp(yxHl7YzYaoPlanPO.getPlanTime());
                    }
                    else{
                        exeYaoOutVO.setStartTimestamp(yxHl7YzYaoPlanPO.getExeTime());
                    }
                }
            });
            BigDecimal yaoUsedCounts = yaoPlanPoList.stream().filter(e -> null != e.getYtCount())
                    // 将user对象的mongey取出来map为Bigdecimal
                    .map(BHl7YzYaoPlan::getYtCount)
                    // 使用reduce聚合函数,实现累加器
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            double totalCounts = yaoPlanPoList.stream().filter(exeYaoShortOutVO -> exeYaoShortOutVO.getDyAmount() != null && "ml".equals(exeYaoShortOutVO.getDyAmountUnit())).mapToDouble(shortVo -> {
                if (StrUtil.isNotBlank(shortVo.getDyAmount())) {
                    return Double.parseDouble(shortVo.getDyAmount());
                }
                return 0;
            }).sum();
            //设置总量 实际用量
            exeYaoOutVO.setTotalCounts(totalCounts);
            exeYaoOutVO.setYaoUsedCounts(yaoUsedCounts);
            //药物列表 主药在前
            List<ExeYaoShortOutVO> yaoList = yaoPlanPoList.stream().sorted(Comparator.comparing(BHl7YzYaoPlan::getIsMaster).reversed()).map(ExeYaoShortOutVO::new).collect(Collectors.toList());
            exeYaoOutVO.setYaoList(yaoList);

            if (yaoPlanPoList.size() > 0) {
                exeYaoOutVO.setPlanTime(yaoPlanPoList.get(0).getPlanTime());
            }

            resultList.add(exeYaoOutVO);
        });


        List<ExeYaoOutVO> result = resultList;

        //根据执行状态条件筛选
        String exeStatus = queryVO.getExeStatus();
        ExeYaoStatusNewEnum exeYaoStatusEnum = ExeYaoStatusNewEnum.forValue(exeStatus);
        if (exeYaoStatusEnum != null) {

            result = result.stream().filter(
                    exeYaoOutVO -> {
                        if(null != exeYaoOutVO.getExeStatus()){
                            return exeYaoOutVO.getExeStatus().equals(exeYaoStatusEnum.getStatusCode());
                        }
                        else{
                            if(exeYaoStatusEnum.getStatusCode().equals("null")){
                                return true;
                            }
                            else{
                                return false;
                            }
                        }
                    }
            ).collect(Collectors.toList());
        }
        //根据排序字段排序
        ExeYaoSortFieldEnum sortFieldEnum = ExeYaoSortFieldEnum.forValue(sortName);
        if (sortFieldEnum != null) {
            switch (sortFieldEnum) {
                case PLAN_TIME:
                    //计划时间升序
                    result = result.stream().filter(e -> null != e.getPlanTime()).sorted(Comparator.comparing(ExeYaoOutVO::getPlanTime)).collect(Collectors.toList());
                    break;
                case EXE_TIME:
                    //执行时间升序
                    result = result.stream().filter(e -> null != e.getStartTimestamp()).sorted(Comparator.comparing(ExeYaoOutVO::getStartTimestamp, Comparator.nullsLast(LocalDateTime::compareTo))).collect(Collectors.toList());
                    break;
                case ST:
                    //st优先后再根据计划时间升序排序
                    result = result.stream().filter(e -> StringUtil.isNotEmpty(e.getRepeatIdent())).sorted(Comparator.comparing(ExeYaoOutVO::getRepeatIdent, Comparator.comparing(ExeYaoSortFieldEnum.ST.getSortName()::equalsIgnoreCase)).reversed().thenComparing(ExeYaoOutVO::getPlanTime)).collect(Collectors.toList());
                    break;
                default:
            }
        }
        else{
            result = resultList.stream().sorted(Comparator.comparing(ExeYaoOutVO::getYaoExeTime,Comparator.nullsLast(LocalDateTime::compareTo))).collect(Collectors.toList());
        }
        return result;
    }


    /**
     * 查询执行用药或出入量明细方法
     *
     * @param inputType 出入量类型
     * @param startTimeStr 开始时间
     * @param endTimeStr    结束时间
     * @param hospitalNumber 住院号
     * @param isIo 是否用于出入量模块（0 不是，1 是）
     * @return
     */
    private List<BHl7YzYaoPlan> selectYaoList(Integer inputType, String startTimeStr,String endTimeStr,String hospitalNumber,Integer isIo
            ,String medicationName,String routeIdent,String conditionIdent,Integer iscare) {

        if(null == isIo){
            return new ArrayList<>();
        }

        //执行用药主药
        List<BHl7YzYaoPlan> yaoPlanList = null;
        if(isIo == YES_NUMBER){
            yaoPlanList  = bHl7YzYaoPlanMapper.selectListByExeTimeQuery(hospitalNumber, null,
                    null, null, startTimeStr, endTimeStr,inputType,iscare, "已执行", NO_NUMBER);
        }
        else{
            yaoPlanList  = bHl7YzYaoPlanMapper.selectListByExeTimeQuery(hospitalNumber, medicationName, routeIdent, conditionIdent, startTimeStr, endTimeStr, inputType);
        }

        //出入量
        List<BHl7YzYaoPlan> yaoPlanList2 = bHl7YzYaoPlanMapper.selectListByExeTimeQuery(hospitalNumber, null,
                null, null, startTimeStr, endTimeStr,inputType,iscare,"已执行",YES_NUMBER);
        //主要为空直接返回
        if (CollectionUtil.isEmpty(yaoPlanList) && CollectionUtil.isEmpty(yaoPlanList2)) {
            return new ArrayList<>();
        }
        List<HashMap<String,Object>> list = new ArrayList<>();
        yaoPlanList.forEach(yaoplan ->{
            HashMap<String,Object> item = new HashMap<>();
            item.put("groupid",yaoplan.getGroupId());
            item.put("plantime",yaoplan.getPlanTime());
            list.add(item);
        });

        //获取主要药gropid和plantime集合
        Set<String> groupIdList = yaoPlanList.stream().map(BHl7YzYaoPlan::getGroupId).collect(Collectors.toSet());
        Set<LocalDateTime> planTimeList = yaoPlanList.stream().map(BHl7YzYaoPlan::getPlanTime).collect(Collectors.toSet());
        //根据groupId和plantime查询主要相关的所有用药计划
        List<BHl7YzYaoPlan> yaoPlanListByGroup = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(yaoPlanList)){
            //List<YxHl7YzYaoPlanPO> listyao = yaoPlanMapper.selectListByGroupIdsAndExeTimeRange(groupIdList,planTimeList,hospitalNumber);
            List<BHl7YzYaoPlan> listyao = bHl7YzYaoPlanMapper.selectListByGroupIdsAndExeTimeRange(list,hospitalNumber);
            if(CollectionUtil.isNotEmpty(listyao)){
                yaoPlanListByGroup.addAll(listyao);
            }
        }
        if(isIo == 1){
            yaoPlanListByGroup.addAll(0,yaoPlanList2);
        }
        return yaoPlanListByGroup;
    }


}


